/**
 * 
 */
package com.cmcc.pcap.packet.capture;


import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.cmcc.pcap.packet.dataObtian.ResolveDataObtain;

import java.io.File;
import java.io.FilenameFilter;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.Queue;

/**
 * @Date 2018年6月14日 下午6:37:11
 * @author Amish
 */
public class PacketAnalysis {
	private static Logger logger = LogManager.getLogger(PacketAnalysis.class);
	//private static int pcapDealThreads = 1;
	
	static FilenameFilter filenameFilter = new FilenameFilter(){
		@Override
		public boolean accept(File file, String name) {//这里的name属性，表示文件或文件夹的名字，
			                                           //可以直接根据名字做前缀、后缀以及正则表达式等进行过滤，
			                                           //如：return name.startsWith("ra");
			return name.matches("(.*\\.pcap)|(.*\\.cap)");
			//return name.contains(".pcap");//性能是否不如正则表达式?
		}
	};
	
	public static void analysis(String taskId,String pcapDir,Class tcpHandler,Class httpHandler,Class httpsHandler) throws Exception {
//		HandlerManager.tcpHandler = tcpHandler;
//		HandlerManager.httpsHandler = httpsHandler;
//		HandlerManager.httpHandler = httpHandler;
		try{
			File dir = new File(pcapDir);
			if( !dir.isDirectory() ){
				logger.error("the input is not a directory ");
				return;
			}
			
			File[] files = dir.listFiles(filenameFilter);
			
			logger.info("the fileNumber is : "+files.length);
			//logger.info("the dir total length is : "+dir.length());//8192
			
			long totalBytes = 0;
			for(File file : files){
				totalBytes += file.length();
				//logger.info("the < "+file.getName()+" > file.lentgh is : "+file.length());
			}
			logger.info("the dir total length is : "+totalBytes);
			
			
			JCaptures jc = new JCaptures(taskId,null,null,null,null,null,null,null);  //赋值标准id,存入数据库表中
			long dealTotalBytes = 0;
			for(File file : files){//TODO file 分组 分给多个jcpatures处理？
				logger.info("the < "+file.getName()+" > file.lentgh is : "+file.length());
				dealTotalBytes += file.length();
				
//				jc.complete = false;
				
				jc.tcp_packet_exist = false;
				jc.udp_packet_exist = false;
				
				jc.tcp_complete = false;
				jc.udp_complete = false;
				
				jc.captureFromFile(file.getAbsolutePath(),null);//fileRealSerial为true时方法内会阻塞等待所有一个文件的包处理完
				//将处理进度写入数据库

				try {
					logger.info("complete : "+ dealTotalBytes +"/ total : "+totalBytes);
					logger.info("the pcap deal rate of progress is : "+ proportionCalculation(dealTotalBytes,totalBytes) +" %");
				} catch (Exception e) {
					e.printStackTrace();
					logger.error("解析数据包进度更新失败!",e);
				}
			}
			int i = 0;
			while(true){
				//有tcp包，没有udp包
				logger.debug("tcp_exist:" + jc.tcp_packet_exist);
				logger.debug("udp_exist:" + jc.udp_packet_exist);
				logger.debug("tcp_complete:" + jc.tcp_complete);
				logger.debug("udp_complete:" + jc.udp_complete);
				
				if(jc.tcp_packet_exist && !jc.udp_packet_exist){
					if(jc.tcp_complete){
						logger.debug("tcp packets deal !");
						break;
					}
						
				}
				//没有tcp包，有udp包
				if(!jc.tcp_packet_exist && jc.udp_packet_exist){
					if(jc.udp_complete){
						logger.debug("udp packets deal !");
						break;
					}
					
				}
				
				//有tcp包，也有udp包
				if(jc.tcp_packet_exist && jc.udp_packet_exist){
					if(jc.tcp_complete && jc.udp_complete){
						logger.debug("tcp and udp packets deal !");
						break;
					}
				}
				//根据过滤条件没有任何数据包
				if (!jc.tcp_complete&&!jc.udp_complete&&!jc.tcp_packet_exist&&!jc.udp_packet_exist){
					if (i>15)
					break;
				}
				i++;
				Thread.sleep(1000);
			}
			jc.stop();//显示调用stop，否则文件处理完也不会结束进程
		} catch (Exception e) {
			logger.error("some exception",e);
			throw new Exception(e);
		}
		
	}

	public static Queue analysis2(String taskId,String pcapDir, Class tcpHandler, Class httpHandler, Class httpsHandler) throws Exception {
//		HandlerManager.tcpHandler = tcpHandler;
//		HandlerManager.httpsHandler = httpsHandler;
//		HandlerManager.httpHandler = httpHandler;
		JCaptures jc = null;
		try{
			File dir = new File(pcapDir);
			if( !dir.isDirectory() ){
				logger.error("the input is not a directory ");
				return null;
			}

			File[] files = dir.listFiles(filenameFilter);

			logger.info("the fileNumber is : "+files.length);
			//logger.info("the dir total length is : "+dir.length());//8192

			long totalBytes = 0;
			for(File file : files){
				totalBytes += file.length();
				//logger.info("the < "+file.getName()+" > file.lentgh is : "+file.length());
			}
			logger.info("the dir total length is : "+totalBytes);


			jc = new JCaptures(taskId,null,null,null,null,null,null,null);  //赋值标准id,存入数据库表中
			long dealTotalBytes = 0;
			for(File file : files){//TODO file 分组 分给多个jcpatures处理？
				logger.info("the < "+file.getName()+" > file.lentgh is : "+file.length());
				dealTotalBytes += file.length();

//				jc.complete = false;

				jc.tcp_packet_exist = false;
				jc.udp_packet_exist = false;

				jc.tcp_complete = false;
				jc.udp_complete = false;

				jc.captureFromFile(file.getAbsolutePath(),null);//fileRealSerial为true时方法内会阻塞等待所有一个文件的包处理完
				//将处理进度写入数据库

				try {
					logger.info("complete : "+ dealTotalBytes +"/ total : "+totalBytes);
					logger.info("the pcap deal rate of progress is : "+ proportionCalculation(dealTotalBytes,totalBytes) +" %");
				} catch (Exception e) {
					e.printStackTrace();
					logger.error("解析数据包进度更新失败!",e);
				}
			}
			int i = 0;
			while(true){
				//有tcp包，没有udp包
				logger.debug("tcp_exist:" + jc.tcp_packet_exist);
				logger.debug("udp_exist:" + jc.udp_packet_exist);
				logger.debug("tcp_complete:" + jc.tcp_complete);
				logger.debug("udp_complete:" + jc.udp_complete);

				if(jc.tcp_packet_exist && !jc.udp_packet_exist){
					if(jc.tcp_complete){
						logger.debug("tcp packets deal !");
						break;
					}

				}
				//没有tcp包，有udp包
				if(!jc.tcp_packet_exist && jc.udp_packet_exist){
					if(jc.udp_complete){
						logger.debug("udp packets deal !");
						break;
					}

				}

				//有tcp包，也有udp包
				if(jc.tcp_packet_exist && jc.udp_packet_exist){
					if(jc.tcp_complete && jc.udp_complete){
						logger.debug("tcp and udp packets deal !");
						break;
					}
				}
				//根据过滤条件没有任何数据包
				if (!jc.tcp_complete&&!jc.udp_complete&&!jc.tcp_packet_exist&&!jc.udp_packet_exist){
					if (i>15)
						break;
				}
				i++;
				Thread.sleep(1000);
			}
		//	jc.stop();//显示调用stop，否则文件处理完也不会结束进程
		} catch (Exception e) {
			logger.error("some exception",e);
			throw new Exception(e);
		} finally {
			if (jc != null) {
				jc.stop();
			}
		}
		return ResolveDataObtain.getResolveDataObtain().getData();
	}

	/**
	 * 此方法目前会有 java.io.IOException:  Another Jpcap instance is being used. TOFix
	 * @param taskId
	 * @param pcapDir
	 * @param callBack
	 * @param quicCallBack
	 * @param tcpcallBack
	 * @param udpcallBack
	 */
	@Deprecated
	public static void analysis2(String taskId , String pcapDir, CallBack callBack, CallBack quicCallBack, CallBack tcpcallBack, CallBack udpcallBack, CallBack sctpcallBack, CallBack ngapcallBack, CallBack pfcpcallBack) {
		try{
			TaskContext tc = new TaskContext(taskId,pcapDir,callBack,quicCallBack,tcpcallBack,udpcallBack,sctpcallBack, ngapcallBack,pfcpcallBack);
			tc.analysisStart();
		} catch (Exception e) {
			logger.error("some exception",e);
		}
	}


	public static Queue analysis2(String taskId, String pcapDir, Class sctpHandler) throws Exception {
		JCaptures jc = null;
		try{
			File dir = new File(pcapDir);
			if( !dir.isDirectory() ){
				logger.error("the input is not a directory ");
				return null;
			}

			File[] files = dir.listFiles(filenameFilter);


			logger.info("the fileNumber is : "+files.length);

			long totalBytes = 0;
			for(File file : files){
				totalBytes += file.length();
				//logger.info("the < "+file.getName()+" > file.lentgh is : "+file.length());
			}
			logger.info("the dir total length is : "+totalBytes);


			jc = new JCaptures(taskId,null,null,null,null,null,null,null);  //赋值标准id,存入数据库表中
			long dealTotalBytes = 0;
			for(File file : files){//TODO file 分组 分给多个jcpatures处理？
				logger.info("the < "+file.getName()+" > file.lentgh is : "+file.length());
				dealTotalBytes += file.length();

				jc.captureFromFile(file.getAbsolutePath(),null);//fileRealSerial为true时方法内会阻塞等待所有一个文件的包处理完
				//将处理进度写入数据库

				try {
					logger.info("complete : "+ dealTotalBytes +"/ total : "+totalBytes);
					logger.info("the pcap deal rate of progress is : "+ proportionCalculation(dealTotalBytes,totalBytes) +" %");
				} catch (Exception e) {
					e.printStackTrace();
					logger.error("解析数据包进度更新失败!",e);
				}
			}
			int i = 0;
			while(true){
				logger.debug("sctp_exist:" + jc.sctp_packet_exist);
				logger.debug("sctp_complete:" + jc.sctp_complete);

				if(jc.sctp_packet_exist ){
					if(jc.sctp_complete){
						logger.debug("sctp packets deal !");
						break;
					}

				}
				//根据过滤条件没有任何数据包
				if (!jc.sctp_packet_exist&&!jc.sctp_complete){
					if (i>15)
						break;
				}
				i++;
				Thread.sleep(1000);
			}
				jc.stop();//显示调用stop，否则文件处理完也不会结束进程
		} catch (Exception e) {
			logger.error("some exception",e);
			throw new Exception(e);
		} finally {
			if (jc != null) {
				jc.stop();
			}
		}
		return ResolveDataObtain.getResolveDataObtain().getData();
	}

	public static Queue analysis3(String taskId, String pcapPath, Class sctpHandler) throws Exception {
		JCaptures jc = null;
		try{
			File file = new File(pcapPath);

			long totalBytes = 0;
			logger.info("the dir total length is : "+totalBytes);


			jc = new JCaptures(taskId,null,null,null,null,null,null,null);  //赋值标准id,存入数据库表中

			logger.info("the < "+file.getName()+" > file.lentgh is : "+file.length());
			jc.captureFromFile(file.getAbsolutePath(),null);//fileRealSerial为true时方法内会阻塞等待所有一个文件的包处理完
			//将处理进度写入数据库

			try {
				logger.info("total : "+totalBytes);
			} catch (Exception e) {
				e.printStackTrace();
				logger.error("解析数据包进度更新失败!",e);
			}
			int i = 0;
			while(true){
				logger.debug("sctp_exist:" + jc.sctp_packet_exist);
				logger.debug("sctp_complete:" + jc.sctp_complete);

				if(jc.sctp_packet_exist ){
					if(jc.sctp_complete){
						logger.debug("sctp packets deal !");
						break;
					}

				}
				//根据过滤条件没有任何数据包
				if (!jc.sctp_packet_exist&&!jc.sctp_complete){
					if (i>15)
						break;
				}
				i++;
				Thread.sleep(1000);
			}
			jc.stop();//显示调用stop，否则文件处理完也不会结束进程
		} catch (Exception e) {
			logger.error("some exception",e);
			throw new Exception(e);
		} finally {
			if (jc != null) {
				jc.stop();
			}
		}
		return ResolveDataObtain.getResolveDataObtain().getData();
	}
	
	
	public static String proportionCalculation(long numerator , long denominator) {
		DecimalFormat decimalFormat = (DecimalFormat) DecimalFormat.getInstance();
		decimalFormat.setMaximumFractionDigits(2);
		decimalFormat.setRoundingMode(RoundingMode.HALF_UP);
		float proportionNum = (float)numerator/(float)denominator * 100;
		
		String proportionStr = decimalFormat.format(proportionNum);
		return proportionStr;
	}
	
	
	
	

}
